﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Aragorn.SOA.Infratructure.Config;
using Aragorn.SOA.Utility;
using ZooKeeperNet;

namespace Aragorn.SOA.Infratructure
{
    public  class ServicesDiscovery
    {
        public ServicesWatcher servicewathcher;

        List<string> service_repos;

        private List<string> servicesType; 

        private List<string> alive_host;

        private IZooKeeper zk;

        ZKConfig config = new ZKConfig();


        public ServicesDiscovery()
        {
            Init();
        }

        //获取所有的服务名称
        public void SelectAllRepository()
        {

            var zk = ZkHelper.GetInstance().ConnectServer(config.Host, new TimeSpan(1, 0, 0), null);
            if (zk == null)
            {
                throw new Exception("无法连接ZK服务器：" + config.Host);
            }
            
            alive_host = new List<string>();
            servicewathcher = new ServicesWatcher(zk);

            servicesType.ForEach(x =>
            { 
               var alive = zk.GetChildren(config.ZK_REGISTRY_PATH + "/" + x, servicewathcher).ToList();
                alive_host=alive_host.Union(alive).ToList();
            });
        }


        //根据分类和服务名字获取可用的节点
        public dynamic SelectRepositoryEndPoint(string category,string servicename)
        {
            var zk = ZkHelper.GetInstance().ConnectServer(config.Host, new TimeSpan(1, 0, 0), null);
            if (zk == null)
            {
                throw new Exception("无法连接ZK服务器：" + config.Host);
            }

            servicewathcher = new ServicesWatcher(zk);

            var  endpoins =zk.GetChildren(config.ZK_REGISTRY_PATH + "/" + category + "/" + servicename, servicewathcher).ToList();
            //获得的所有endpoints节点 需要通过一定的规则和算法（例如轮询，加权和hash值算法），给出唯一地址,现在默认给出第一个
            

            return endpoins.First();
        }

        //启动的时候获取zookeeper的所有节点缓存到service_repos对象中
        public void Init()
        {

            //判断默认节点是否存在,不存在则创建
            //zk = new ZooKeeper("192.168.1.126:2181", new TimeSpan(1,0,0),null );
            //Thread.Sleep(1000);

            var zk = ZkHelper.GetInstance().ConnectServer(config.Host, new TimeSpan(1, 0, 0), null);
            if (zk==null)
            {
                throw  new Exception("无法连接ZK服务器："+config.Host);
            }

            if (zk.Exists(config.ZK_REGISTRY_PATH, false) == null)
                zk.Create(config.ZK_REGISTRY_PATH, null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);


            servicesType = new List<string>();

            //只能获取下一级的节点
            //所有的服务类别
            servicesType = zk.GetChildren(config.ZK_REGISTRY_PATH, null).ToList(); //test
        }


        //根据服务分类获取该分类下的所有服务
        public dynamic SelectRepositoryByCategory(string Category)
        {

            var zk = ZkHelper.GetInstance().ConnectServer(config.Host, new TimeSpan(1, 0, 0), null);
            if (zk == null)
            {
                throw new Exception("无法连接ZK服务器：" + config.Host);
            }


            //
            service_repos = zk.GetChildren(config.ZK_REGISTRY_PATH + "/" + Category, null).ToList();

            return service_repos;
        }



        private void WatchNode(ZooKeeper zk)
        {
            
        }


        private ZooKeeper ConnectServer()
        {

            zk = ZkHelper.GetInstance().ConnectServer(config.Host, new TimeSpan(1, 0, 0), null);
            return (ZooKeeper)zk;
        }



        //通过Zookeeper的Watcher机制来实时更新本地缓存service_repos
        public bool UpdateRepository()
        {
            return false;
        }
    }
}
